home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-I386 / SPINLOCK.H < prev    next >
C/C++ Source or Header  |  1999-09-17  |  9KB  |  255 lines

  1. #ifndef __ASM_SPINLOCK_H
  2. #define __ASM_SPINLOCK_H
  3.  
  4. #ifndef __SMP__
  5.  
  6. #define DEBUG_SPINLOCKS    0    /* 0 == no debugging, 1 == maintain lock state, 2 == full debug */
  7.  
  8. #if (DEBUG_SPINLOCKS < 1)
  9.  
  10. /*
  11.  * Your basic spinlocks, allowing only a single CPU anywhere
  12.  *
  13.  * Gcc-2.7.x has a nasty bug with empty initializers.
  14.  */
  15. #if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)
  16.   typedef struct { } spinlock_t;
  17.   #define SPIN_LOCK_UNLOCKED (spinlock_t) { }
  18. #else
  19.   typedef struct { int gcc_is_buggy; } spinlock_t;
  20.   #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
  21. #endif
  22.  
  23. #define spin_lock_init(lock)    do { } while(0)
  24. #define spin_lock(lock)        do { } while(0)
  25. #define spin_trylock(lock)    (1)
  26. #define spin_unlock_wait(lock)    do { } while(0)
  27. #define spin_unlock(lock)    do { } while(0)
  28. #define spin_lock_irq(lock)    cli()
  29. #define spin_unlock_irq(lock)    sti()
  30.  
  31. #define spin_lock_irqsave(lock, flags) \
  32.     do { save_flags(flags); cli(); } while (0)
  33. #define spin_unlock_irqrestore(lock, flags) \
  34.     restore_flags(flags)
  35.  
  36. #elif (DEBUG_SPINLOCKS < 2)
  37.  
  38. typedef struct {
  39.     volatile unsigned int lock;
  40. } spinlock_t;
  41. #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
  42.  
  43. #define spin_lock_init(x)    do { (x)->lock = 0; } while (0)
  44. #define spin_trylock(lock)    (!test_and_set_bit(0,(lock)))
  45.  
  46. #define spin_lock(x)        do { (x)->lock = 1; } while (0)
  47. #define spin_unlock_wait(x)    do { } while (0)
  48. #define spin_unlock(x)        do { (x)->lock = 0; } while (0)
  49. #define spin_lock_irq(x)    do { cli(); spin_lock(x); } while (0)
  50. #define spin_unlock_irq(x)    do { spin_unlock(x); sti(); } while (0)
  51.  
  52. #define spin_lock_irqsave(x, flags) \
  53.     do { save_flags(flags); spin_lock_irq(x); } while (0)
  54. #define spin_unlock_irqrestore(x, flags) \
  55.     do { spin_unlock(x); restore_flags(flags); } while (0)
  56.  
  57. #else /* (DEBUG_SPINLOCKS >= 2) */
  58.  
  59. typedef struct {
  60.     volatile unsigned int lock;
  61.     volatile unsigned int babble;
  62.     const char *module;
  63. } spinlock_t;
  64. #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 25, __BASE_FILE__ }
  65.  
  66. #include <linux/kernel.h>
  67.  
  68. #define spin_lock_init(x)    do { (x)->lock = 0; } while (0)
  69. #define spin_trylock(lock)    (!test_and_set_bit(0,(lock)))
  70.  
  71. #define spin_lock(x)        do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1; restore_flags(__spinflags);} while (0)
  72. #define spin_unlock_wait(x)    do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock_wait(%s:%p) deadlock\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} restore_flags(__spinflags);} while (0)
  73. #define spin_unlock(x)        do {unsigned long __spinflags; save_flags(__spinflags); cli(); if (!(x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock(%s:%p) not locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(__spinflags);} while (0)
  74. #define spin_lock_irq(x)    do {cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock_irq(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1;} while (0)
  75. #define spin_unlock_irq(x)    do {cli(); if (!(x)->lock&&(x)->babble) {printk("%s:%d: spin_lock(%s:%p) not locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; sti();} while (0)
  76.  
  77. #define spin_lock_irqsave(x,flags)      do {save_flags(flags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock_irqsave(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1;} while (0)
  78. #define spin_unlock_irqrestore(x,flags) do {cli(); if (!(x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock_irqrestore(%s:%p) not locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(flags);} while (0)
  79.  
  80. #endif    /* DEBUG_SPINLOCKS */
  81.  
  82. /*
  83.  * Read-write spinlocks, allowing multiple readers
  84.  * but only one writer.
  85.  *
  86.  * NOTE! it is quite common to have readers in interrupts
  87.  * but no interrupt writers. For those circumstances we
  88.  * can "mix" irq-safe locks - any writer needs to get a
  89.  * irq-safe write-lock, but readers can get non-irqsafe
  90.  * read-locks.
  91.  *
  92.  * Gcc-2.7.x has a nasty bug with empty initializers.
  93.  */
  94. #if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)
  95.   typedef struct { } rwlock_t;
  96.   #define RW_LOCK_UNLOCKED (rwlock_t) { }
  97. #else
  98.   typedef struct { int gcc_is_buggy; } rwlock_t;
  99.   #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
  100. #endif
  101.  
  102. #define read_lock(lock)        do { } while(0)
  103. #define read_unlock(lock)    do { } while(0)
  104. #define write_lock(lock)    do { } while(0)
  105. #define write_unlock(lock)    do { } while(0)
  106. #define read_lock_irq(lock)    cli()
  107. #define read_unlock_irq(lock)    sti()
  108. #define write_lock_irq(lock)    cli()
  109. #define write_unlock_irq(lock)    sti()
  110.  
  111. #define read_lock_irqsave(lock, flags)    \
  112.     do { save_flags(flags); cli(); } while (0)
  113. #define read_unlock_irqrestore(lock, flags) \
  114.     restore_flags(flags)
  115. #define write_lock_irqsave(lock, flags)    \
  116.     do { save_flags(flags); cli(); } while (0)
  117. #define write_unlock_irqrestore(lock, flags) \
  118.     restore_flags(flags)
  119.  
  120. #else    /* __SMP__ */
  121.  
  122. /*
  123.  * Your basic spinlocks, allowing only a single CPU anywhere
  124.  */
  125.  
  126. typedef struct {
  127.     volatile unsigned int lock;
  128. } spinlock_t;
  129.  
  130. #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
  131.  
  132. #define spin_lock_init(x)    do { (x)->lock = 0; } while(0)
  133. /*
  134.  * Simple spin lock operations.  There are two variants, one clears IRQ's
  135.  * on the local processor, one does not.
  136.  *
  137.  * We make no fairness assumptions. They have a cost.
  138.  */
  139.  
  140. #define spin_unlock_wait(x)    do { barrier(); } while(((volatile spinlock_t *)(x))->lock)
  141.  
  142. typedef struct { unsigned long a[100]; } __dummy_lock_t;
  143. #define __dummy_lock(lock) (*(__dummy_lock_t *)(lock))
  144.  
  145. #define spin_lock_string \
  146.     "\n1:\t" \
  147.     "lock ; btsl $0,%0\n\t" \
  148.     "jc 2f\n" \
  149.     ".section .text.lock,\"ax\"\n" \
  150.     "2:\t" \
  151.     "testb $1,%0\n\t" \
  152.     "jne 2b\n\t" \
  153.     "jmp 1b\n" \
  154.     ".previous"
  155.  
  156. #define spin_unlock_string \
  157.     "lock ; btrl $0,%0"
  158.  
  159. #define spin_lock(lock) \
  160. __asm__ __volatile__( \
  161.     spin_lock_string \
  162.     :"=m" (__dummy_lock(lock)))
  163.  
  164. #define spin_unlock(lock) \
  165. __asm__ __volatile__( \
  166.     spin_unlock_string \
  167.     :"=m" (__dummy_lock(lock)))
  168.  
  169. #define spin_trylock(lock) (!test_and_set_bit(0,(lock)))
  170.  
  171. #define spin_lock_irq(lock) \
  172.     do { __cli(); spin_lock(lock); } while (0)
  173.  
  174. #define spin_unlock_irq(lock) \
  175.     do { spin_unlock(lock); __sti(); } while (0)
  176.  
  177. #define spin_lock_irqsave(lock, flags) \
  178.     do { __save_flags(flags); __cli(); spin_lock(lock); } while (0)
  179.  
  180. #define spin_unlock_irqrestore(lock, flags) \
  181.     do { spin_unlock(lock); __restore_flags(flags); } while (0)
  182.  
  183. /*
  184.  * Read-write spinlocks, allowing multiple readers
  185.  * but only one writer.
  186.  *
  187.  * NOTE! it is quite common to have readers in interrupts
  188.  * but no interrupt writers. For those circumstances we
  189.  * can "mix" irq-safe locks - any writer needs to get a
  190.  * irq-safe write-lock, but readers can get non-irqsafe
  191.  * read-locks.
  192.  */
  193. typedef struct {
  194.     volatile unsigned int lock;
  195.     unsigned long previous;
  196. } rwlock_t;
  197.  
  198. #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
  199.  
  200. /*
  201.  * On x86, we implement read-write locks as a 32-bit counter
  202.  * with the high bit (sign) being the "write" bit.
  203.  *
  204.  * The inline assembly is non-obvious. Think about it.
  205.  */
  206. #define read_lock(rw)    \
  207.     asm volatile("\n1:\t" \
  208.              "lock ; incl %0\n\t" \
  209.              "js 2f\n" \
  210.              ".section .text.lock,\"ax\"\n" \
  211.              "2:\tlock ; decl %0\n" \
  212.              "3:\tcmpl $0,%0\n\t" \
  213.              "js 3b\n\t" \
  214.              "jmp 1b\n" \
  215.              ".previous" \
  216.              :"=m" (__dummy_lock(&(rw)->lock)))
  217.  
  218. #define read_unlock(rw) \
  219.     asm volatile("lock ; decl %0" \
  220.         :"=m" (__dummy_lock(&(rw)->lock)))
  221.  
  222. #define write_lock(rw) \
  223.     asm volatile("\n1:\t" \
  224.              "lock ; btsl $31,%0\n\t" \
  225.              "jc 4f\n" \
  226.              "2:\ttestl $0x7fffffff,%0\n\t" \
  227.              "jne 3f\n" \
  228.              ".section .text.lock,\"ax\"\n" \
  229.              "3:\tlock ; btrl $31,%0\n" \
  230.              "4:\tcmp $0,%0\n\t" \
  231.              "jne 4b\n\t" \
  232.              "jmp 1b\n" \
  233.              ".previous" \
  234.              :"=m" (__dummy_lock(&(rw)->lock)))
  235.  
  236. #define write_unlock(rw) \
  237.     asm volatile("lock ; btrl $31,%0":"=m" (__dummy_lock(&(rw)->lock)))
  238.  
  239. #define read_lock_irq(lock)    do { __cli(); read_lock(lock); } while (0)
  240. #define read_unlock_irq(lock)    do { read_unlock(lock); __sti(); } while (0)
  241. #define write_lock_irq(lock)    do { __cli(); write_lock(lock); } while (0)
  242. #define write_unlock_irq(lock)    do { write_unlock(lock); __sti(); } while (0)
  243.  
  244. #define read_lock_irqsave(lock, flags)    \
  245.     do { __save_flags(flags); __cli(); read_lock(lock); } while (0)
  246. #define read_unlock_irqrestore(lock, flags) \
  247.     do { read_unlock(lock); __restore_flags(flags); } while (0)
  248. #define write_lock_irqsave(lock, flags)    \
  249.     do { __save_flags(flags); __cli(); write_lock(lock); } while (0)
  250. #define write_unlock_irqrestore(lock, flags) \
  251.     do { write_unlock(lock); __restore_flags(flags); } while (0)
  252.  
  253. #endif /* __SMP__ */
  254. #endif /* __ASM_SPINLOCK_H */
  255.